package com.hsav.kcxb.view;

import android.content.Context;
import android.graphics.Rect;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.widget.ViewDragHelper;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.hsav.kcxb.R;
import com.hsav.kcxb.utils.DensityUtil;
import com.hsav.kcxb.utils.LrcEntry;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by gf on 2017/6/28.
 */

public class MusicClipContainer extends FrameLayout {
    private static final String TAG = MusicClipContainer.class.getName();
    private ViewDragHelper viewDragHelper;
    private View startHandler;
    private View endHandler;
    private int startHandlerMinTop;
    private int startHandlerMaxTop;
    private int endHandlerMinTop;
    private int endHandlerMaxTop;
    private ViewDragHelper.Callback callback = new ViewDragHelper.Callback() {
        private View draggedView;

        @Override
        public boolean tryCaptureView(View view, int i) {
            draggedView = view;
            return draggedView == startHandler || draggedView == endHandler;
        }

        @Override
        public int clampViewPositionVertical(View child, int top, int dy) {
            if (draggedView == startHandler)
            {
                if (top + startHandler.getHeight() >= endHandler.getTop())
                {
                    int newTop = endHandler.getTop() + dy;
                    newTop = Math.min(Math.max(newTop, startHandler.getBottom()), endHandlerMaxTop);
                    endHandler.layout(endHandler.getLeft(), newTop, endHandler.getRight(), newTop + endHandler.getHeight());
                }

                return Math.min(Math.max(top, startHandlerMinTop), startHandlerMaxTop);
            }
            else
            {
                if (top <= startHandler.getBottom())
                {
                    int newTop = startHandler.getTop() + dy;
                    newTop = Math.min(Math.max(newTop, startHandlerMinTop), endHandler.getTop());
                    startHandler.layout(startHandler.getLeft(), newTop, startHandler.getRight(), newTop + startHandler.getHeight());
                }

                return Math.min(Math.max(top, endHandlerMinTop), endHandlerMaxTop);
            }
        }

        @Override
        public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
            if (changedView == startHandler)
            {
                updateUpBounds();
            }
            else
            {
                updateBelowBounds();
            }
        }
    };

    private LinearLayout lrcContainer;
    private List<LrcEntry> lrcEntries;
    private List<TextView> lrcTextViews;
    private TextView startThumb;
    private TextView endThumb;
    private boolean initialized;
    private long startTime;
    private long endTime;
    private long timeLength;

    public MusicClipContainer(Context context)
    {
        super(context);
        viewDragHelper = ViewDragHelper.create(this, 1, callback);
        createContent();
    }

    public MusicClipContainer(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public void loadLrc(final File lrcFile) {
        lrcEntries = LrcEntry.parseLrc(lrcFile);
        lrcTextViews = new ArrayList<>(lrcEntries.size());
        if (lrcEntries.size() == 0) return;
        timeLength = lrcEntries.get(lrcEntries.size() - 1).getTime();
        startTime = (long) (0.3f * timeLength);
        endTime = (long) (0.4f * timeLength);
        inflateLrc(lrcEntries);
    }

    public void setStartTime(long time)
    {
        if (time < 0 || time > timeLength) return;
        if (time > endTime)
        {
            startTime = endTime;
            endTime = time;
            locateStartHandle();
            locateEndHandle();
        }
        else
        {
            startTime = time;
            locateStartHandle();
        }
    }

    public long getStartTime()
    {
        startTime = 0;
        int startLineTop = startHandler.getTop() + startHandler.getHeight() / 2;
        for (int i = 0; i < lrcTextViews.size(); i++)
        {
            TextView textView = lrcTextViews.get(i);
            int textViewTop = lrcContainer.getTop() + textView.getTop();
            if (textViewTop >= startLineTop)
            {
                startTime = lrcEntries.get(i).getTime();
                break;
            }
        }
        return startTime;
    }

    public void setEndTime(long time)
    {
        if (time < 0 || time > timeLength) return;
        if (time < startTime)
        {
            endTime = startTime;
            startTime = time;
            locateStartHandle();
            locateEndHandle();
        }
        else
        {
            endTime = time;
            locateEndHandle();
        }
    }

    public long getEndTime()
    {
        endTime = 0;
        int endLineTop = endHandler.getTop() + endHandler.getHeight() / 2;
        for (int i = 0; i < lrcTextViews.size(); i++)
        {
            TextView textView = lrcTextViews.get(i);
            int textViewTop = lrcContainer.getTop() + textView.getTop();
            if (textViewTop >= endLineTop)
            {
                endTime = lrcEntries.get(i).getTime();
                break;
            }
        }
        return endTime;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);

        if (!initialized)
        {
            initialized = true;
            LayoutParams params = (LayoutParams) lrcContainer.getLayoutParams();
            params.setMargins(0, startHandler.getHeight() / 2, 0, startHandler.getHeight() / 2);
            lrcContainer.setLayoutParams(params);
        }

        startHandlerMinTop = getPaddingTop();
        startHandlerMaxTop = getHeight() - getPaddingBottom() - endHandler.getHeight() - startHandler.getHeight();
        endHandlerMinTop = getPaddingTop() + startHandler.getHeight();
        endHandlerMaxTop = getHeight() - getPaddingBottom() - endHandler.getHeight();

        locateEndHandle();
        locateStartHandle();
    }

    private void updateBelowBounds() {
        int startLineTop = startHandler.getTop() + startHandler.getHeight() / 2;
        int endLineTop = endHandler.getTop() + endHandler.getHeight() / 2;
        for (int i = 0; i < lrcEntries.size(); i++)
        {
            TextView textView = lrcTextViews.get(i);
            int textViewTop = textView.getTop() + lrcContainer.getTop();
            if (textViewTop > endLineTop)
            {
                textView.setTextColor(getResources().getColor(R.color.colorPrimaryDark2));
            }
            else if (textViewTop <= endLineTop && textViewTop > startLineTop)
            {
                textView.setTextColor(getResources().getColor(R.color.color_white_normal));
            }
        }
    }

    private void updateUpBounds() {
        int startLineTop = startHandler.getTop() + startHandler.getHeight() / 2;
        int endLineTop = endHandler.getTop() + endHandler.getHeight() / 2;
        for (int i = 0; i < lrcEntries.size(); i++)
        {
            TextView textView = lrcTextViews.get(i);
            int textViewTop = textView.getTop() + lrcContainer.getTop();
            if (textViewTop < startLineTop)
            {
                textView.setTextColor(getResources().getColor(R.color.colorPrimaryDark2));
            }
            else if (textViewTop > startLineTop && textViewTop <= endLineTop)
            {
                textView.setTextColor(getResources().getColor(R.color.color_white_normal));
            }
        }
    }

    private void locateEndHandle() {
        int top = (int) (((float)endTime / (float) timeLength) * (getHeight() - endHandler.getHeight()));
        endHandler.layout(endHandler.getLeft(), top, endHandler.getRight(), endHandler.getHeight() + top);
        updateBelowBounds();
    }

    private void locateStartHandle() {
        int top = (int) (((float)startTime / (float) timeLength) * (getHeight() - startHandler.getHeight()));
        startHandler.layout(startHandler.getLeft(), top, startHandler.getRight(), startHandler.getHeight() + top);
        updateUpBounds();
    }

    private void createContent() {
        lrcContainer = new LinearLayout(getContext());
        lrcContainer.setOrientation(LinearLayout.VERTICAL);
        lrcContainer.setGravity(Gravity.CENTER_HORIZONTAL);
        LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        lrcContainer.setLayoutParams(params);
        addView(lrcContainer);

        startHandler = LayoutInflater.from(getContext()).inflate(R.layout.content_music_clip_start_handler, this, false);
        startThumb = (TextView) startHandler.findViewById(R.id.thumb);
        addView(startHandler);

        endHandler = LayoutInflater.from(getContext()).inflate(R.layout.content_music_clip_end_handler, this, false);
        endThumb = (TextView) endHandler.findViewById(R.id.thumb);
        addView(endHandler);
    }

    private void inflateLrc(List<LrcEntry> lrcEntries) {
        if (lrcEntries == null || lrcEntries.size() == 0) return;
        for (LrcEntry lrcEntry : lrcEntries)
        {
            TextView line = createLine(lrcEntry);
            lrcTextViews.add(line);
            lrcContainer.addView(line);
        }
    }

    private TextView createLine(LrcEntry lrcEntry) {
        TextView textView = new TextView(getContext());
        textView.setText(lrcEntry.getText());
        textView.setTextColor(getResources().getColor(R.color.color_white_normal));
        LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        int span = DensityUtil.dip2px(getContext(), 4);
        layoutParams.setMargins(0, span, 0, span);
        textView.setLayoutParams(layoutParams);
        return textView;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return viewDragHelper.shouldInterceptTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        viewDragHelper.processTouchEvent(event);
        return true;
    }

    @Override
    public void computeScroll() {
        if (viewDragHelper.continueSettling(true))
        {
            postInvalidate();
        }
    }

    public boolean isClipping(float x, float y) {
        int[] locations = new int[2];
        startThumb.getLocationOnScreen(locations);
        Rect startThumbRect = new Rect(locations[0], locations[1], locations[0] + startThumb.getWidth(), locations[1] + startThumb.getHeight());
        endThumb.getLocationOnScreen(locations);
        Rect endThumbRect = new Rect(locations[0], locations[1], locations[0] + endThumb.getWidth(), locations[1] + endThumb.getHeight());

        boolean isInsideStartThumb = startThumbRect.contains((int) x, (int) y);
        boolean isInsideEndThumb = endThumbRect.contains((int) x, (int) y);
        return  isInsideStartThumb || isInsideEndThumb;
    }
}
